home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / hplip / sendfax.py < prev    next >
Text File  |  2008-10-13  |  26KB  |  760 lines

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program; if not, write to the Free Software
  18. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  19. #
  20. # Author: Don Welch
  21. #
  22. # Thanks to Henrique M. Holschuh <hmh@debian.org> for various security patches
  23. #
  24.  
  25. __version__ = '8.1'
  26. __title__ = 'PC Sendfax Utility'
  27. __doc__ = "Allows for sending faxes from the PC using HPLIP supported multifunction printers." 
  28.  
  29. # Std Lib
  30. import sys
  31. import os
  32. import os.path
  33. import getopt
  34. import signal
  35. import time
  36.  
  37. # Local
  38. from base.g import *
  39. import base.utils as utils
  40. from base import device, tui
  41.  
  42. log.set_module('hp-sendfax')
  43.  
  44. USAGE = [(__doc__, "", "name", True),
  45.          ("Usage: hp-sendfax [PRINTER|DEVICE-URI] [OPTIONS] [MODE] [FILES]", "", "summary", True),
  46.          utils.USAGE_ARGS,
  47.          ("To specify a fax-URI:", "-d<device-uri> or --device=<device-uri>", "option", False),
  48.          ("To specify a CUPS fax:", "--fax=<fax>", "option", False),
  49.          utils.USAGE_SPACE,
  50.          ("[MODE]", "", "header", False),
  51.          ("Enter graphical UI mode:", "-u or --gui (Default)", "option", False),
  52.          ("Run in non-interactive mode (batch mode):", "-n or --non-interactive", "option", False),
  53.          utils.USAGE_SPACE,
  54.          utils.USAGE_OPTIONS,
  55.          ("Specify the fax number(s):", "-f<number(s)> or --faxnum=<number(s)> (-n only)", "option", False),
  56.          ("Specify the recipient(s):", "-r<recipient(s)> or --recipient=<recipient(s)> (-n only)", "option", False), 
  57.          ("Specify the groups(s):", "-g<group(s)> or --group=<group(s)> (-n only)", "option", False), 
  58.          utils.USAGE_BUS1, utils.USAGE_BUS2,         
  59.          utils.USAGE_LOGGING1, utils.USAGE_LOGGING2,
  60.          ("Run in debug mode:", "--gg (same as option: -ldebug)", "option", False),
  61.          utils.USAGE_LANGUAGE,
  62.          utils.USAGE_HELP,
  63.          ("[FILES]", "", "header", False),
  64.          ("A list of files to add to the fax job.", "(Required for -n, optional for -u)", "option", True),
  65.          utils.USAGE_NOTES,
  66.          utils.USAGE_STD_NOTES1,
  67.          ("2. If --fax=\* is specified, the default CUPS fax (printer queue) will be used.", "", "note", False),
  68.          ("3. Coversheets are not supported in non-interactive mode (-n)", "", "note", False),
  69.          ("4. Fax numbers and/or recipients should be listed in comma separated lists (-n only).", "", "note", False),
  70.          utils.USAGE_SPACE,
  71.          utils.USAGE_SEEALSO,
  72.          ("hp-fab", "", "seealso", False),
  73.         ]
  74.  
  75. def usage(typ='text'):
  76.     if typ == 'text':
  77.         utils.log_title(__title__, __version__)
  78.  
  79.     utils.format_text(USAGE, typ, __title__, 'hp-sendfax', __version__)
  80.     sys.exit(0)
  81.  
  82.  
  83.  
  84. prop.prog = sys.argv[0]
  85.  
  86. device_uri = None
  87. printer_name = None
  88. username = prop.username
  89. mode = GUI_MODE
  90. mode_specified = False
  91. faxnum_list = []
  92. recipient_list = []
  93. group_list = []
  94. bus = device.DEFAULT_PROBE_BUS
  95. prettyprint = False
  96. loc = None
  97.  
  98. try:
  99.     opts, args = getopt.getopt(sys.argv[1:],'l:hz:d:b:g:unf:r:tq:', 
  100.         ['device=', 'fax=', 'level=', 
  101.          'help', 'help-rest', 'lang=',
  102.          'help-man', 'logfile=', 'bus=',
  103.          'gui', 'non-interactive', 'logging=',
  104.          'faxnum=', 'recipients=',
  105.          'gg', 'group=', 'help-desc'])
  106.  
  107. except getopt.GetoptError, e:
  108.     log.error(e.msg)
  109.     sys.exit(1)
  110.  
  111.  
  112. if os.getenv("HPLIP_DEBUG"):
  113.     log.set_level('debug')
  114.  
  115. for o, a in opts:
  116.     if o in ('-l', '--logging'):
  117.         log_level = a.lower().strip()
  118.         if not log.set_level(log_level):
  119.             usage()
  120.  
  121.     elif o == '--gg':
  122.         log.set_level('debug')
  123.  
  124.     elif o in ('-z', '--logfile'):
  125.         log.set_logfile(a)
  126.         log.set_where(log.LOG_TO_CONSOLE_AND_FILE)
  127.  
  128.     elif o in ('-h', '--help'):
  129.         usage()
  130.  
  131.     elif o == '--help-rest':
  132.         usage('rest')
  133.  
  134.     elif o == '--help-man':
  135.         usage('man')
  136.  
  137.     elif o == '--help-desc':
  138.         print __doc__,
  139.         sys.exit(0)
  140.  
  141.     elif o in ('-d', '--device'):
  142.         device_uri = a
  143.  
  144.     #elif o in ('-p', '--printer'):
  145.     elif o == '--fax':
  146.         printer_name = a
  147.  
  148.     elif o in ('-b', '--bus'):
  149.         bus = [x.lower().strip() for x in a.split(',')]
  150.         if not device.validateBusList(bus):
  151.             usage()
  152.  
  153.     elif o in ('-n', '--non-interactive'):
  154.         if mode_specified:
  155.             log.error("You may only specify a single mode as a parameter (-n or -u).")
  156.             sys.exit(1)
  157.  
  158.         mode = NON_INTERACTIVE_MODE
  159.         mode_specified = True
  160.  
  161.     elif o in ('-u', '--gui'):
  162.         if mode_specified:
  163.             log.error("You may only specify a single mode as a parameter (-n or -u).")
  164.             sys.exit(1)
  165.  
  166.         mode = GUI_MODE
  167.         mode_specified = True
  168.  
  169.     elif o in ('-f', '--faxnum'):
  170.         faxnum_list.extend(a.split(','))
  171.  
  172.     elif o in ('-r', '--recipient'):
  173.         recipient_list.extend(a.split(','))
  174.  
  175.     elif o in ('-g', '--group'):
  176.         group_list.extend(a.split(','))
  177.  
  178.     elif o in ('-q', '--lang'):
  179.         if a.strip() == '?':
  180.             tui.show_languages()
  181.             sys.exit(0)
  182.  
  183.         loc = utils.validate_language(a.lower())
  184.  
  185.  
  186.  
  187. utils.log_title(__title__, __version__)
  188.  
  189. # Security: Do *not* create files that other users can muck around with
  190. os.umask (0037)
  191.  
  192. if not prop.fax_build:
  193.     log.error("Fax is disabled (turned off during build). Exiting")
  194.     sys.exit(1)
  195.  
  196. if mode == GUI_MODE:
  197.     if not utils.canEnterGUIMode():
  198.         mode = NON_INTERACTIVE_MODE
  199.  
  200. if mode == GUI_MODE:
  201.     app = None
  202.     sendfax = None
  203.  
  204.     from qt import *
  205.  
  206.     # UI Forms
  207.     from ui.faxsendjobform import FaxSendJobForm
  208.  
  209.     # create the main application object
  210.     app = QApplication(sys.argv)
  211.  
  212.     if loc is None:
  213.         loc = user_cfg.ui.get("loc", "system")
  214.         if loc.lower() == 'system':
  215.             loc = str(QTextCodec.locale())
  216.             log.debug("Using system locale: %s" % loc)
  217.  
  218.     if loc.lower() != 'c':
  219.         e = 'utf8'
  220.         try:
  221.             l, x = loc.split('.')
  222.             loc = '.'.join([l, e])
  223.         except ValueError:
  224.             l = loc
  225.             loc = '.'.join([loc, e])
  226.  
  227.         log.debug("Trying to load .qm file for %s locale." % loc)
  228.         trans = QTranslator(None)
  229.  
  230.         qm_file = 'hplip_%s.qm' % l
  231.         log.debug("Name of .qm file: %s" % qm_file)
  232.         loaded = trans.load(qm_file, prop.localization_dir)
  233.  
  234.         if loaded:
  235.             app.installTranslator(trans)
  236.         else:
  237.             loc = 'c'
  238.  
  239.     if loc == 'c':
  240.         log.debug("Using default 'C' locale")
  241.     else:
  242.         log.debug("Using locale: %s" % loc)
  243.  
  244.         QLocale.setDefault(QLocale(loc))
  245.         prop.locale = loc
  246.         try:
  247.             locale.setlocale(locale.LC_ALL, locale.normalize(loc))
  248.         except locale.Error:
  249.             pass
  250.             
  251.             
  252.     if os.geteuid() == 0:
  253.         log.error("You must not be root to run this utility.")
  254.  
  255.         QMessageBox.critical(None, 
  256.                              "HP Device Manager - Send Fax",
  257.                              "You must not be root to run hp-sendfax.",
  258.                               QMessageBox.Ok,
  259.                               QMessageBox.NoButton,
  260.                               QMessageBox.NoButton)
  261.  
  262.         sys.exit(1)
  263.             
  264.  
  265.  
  266.     sendfax = FaxSendJobForm(device_uri,  
  267.                              printer_name, 
  268.                              args) 
  269.  
  270.     app.setMainWidget(sendfax)
  271.  
  272.     pid = os.getpid()
  273.     log.debug('pid=%d' % pid)
  274.  
  275.     sendfax.show()
  276.  
  277.     #signal.signal(signal.SIGPIPE, signal.SIG_IGN)
  278.  
  279.     try:
  280.         log.debug("Starting GUI loop...")
  281.         app.exec_loop()
  282.     except KeyboardInterrupt:
  283.         pass
  284.  
  285.  
  286.  
  287.  
  288. else: # NON_INTERACTIVE_MODE
  289.     if os.getuid() == 0:
  290.         log.error("hp-sendfax cannot be run as root.")
  291.         sys.exit(1)
  292.     
  293.  
  294.     try:
  295.         import struct, Queue
  296.  
  297.         from prnt import cups
  298.         from base import magic
  299.  
  300.         try:
  301.             from fax import fax
  302.         except ImportError:
  303.             # This can fail on Python < 2.3 due to the datetime module
  304.             log.error("Fax address book disabled - Python 2.3+ required.")
  305.             sys.exit(1)    
  306.  
  307.         db =  fax.FaxAddressBook() # FAB instance
  308.  
  309.         try:
  310.             import dbus
  311.         except ImportError:
  312.             log.error("PC send fax requires dbus and python-dbus")
  313.             sys.exit(1)
  314.  
  315.         dbus_avail, service = device.init_dbus()
  316.  
  317.         phone_num_list = []
  318.  
  319.         log.debug("Faxnum list = %s" % faxnum_list)
  320.         faxnum_list = utils.uniqueList(faxnum_list)
  321.         log.debug("Unique list=%s" % faxnum_list)
  322.  
  323.         for f in faxnum_list:
  324.             for c in f:
  325.                 if c not in '0123456789-(+) *#':
  326.                     log.error("Invalid character in fax number '%s'. Only the characters '0123456789-(+) *#' are valid." % f)
  327.                     sys.exit(1)
  328.  
  329.         log.debug("Group list = %s" % group_list)
  330.         group_list = utils.uniqueList(group_list)
  331.         log.debug("Unique list=%s" % group_list)
  332.  
  333.         for g in group_list:
  334.             entries = db.group_members(g)
  335.             if not entries:
  336.                 log.warn("Unknown group name: %s" % g)
  337.             else:
  338.                 for e in entries:
  339.                     recipient_list.append(e)
  340.  
  341.         log.debug("Recipient list = %s" % recipient_list)
  342.         recipient_list = utils.uniqueList(recipient_list)
  343.         log.debug("Unique list=%s" % recipient_list)
  344.  
  345.         for r in recipient_list:
  346.             if db.get(r) is None:
  347.                 log.error("Unknown fax recipient '%s' in the recipient list." % r)
  348.                 all_entries = db.get_all_records()
  349.                 log.info(log.bold("\nKnown recipients (entries):"))
  350.  
  351.                 for a in all_entries:
  352.                     aa = db.get(a)
  353.                     log.info("%s (fax number: %s)" % (a, aa['fax']))
  354.  
  355.                 print
  356.                 sys.exit(1)
  357.  
  358.         for p in recipient_list:
  359.             a = db.get(p)
  360.             phone_num_list.append(a)
  361.             log.debug("Name=%s Number=%s" % (a['name'], a['fax']))
  362.  
  363.         for p in faxnum_list:
  364.             phone_num_list.append({'fax': p, 'name': u'Unknown'})
  365.             log.debug("Number=%s" % p)
  366.  
  367.         log.debug("Phone num list = %s" % phone_num_list)
  368.  
  369.         if not phone_num_list:
  370.             log.error("No recipients specified. Please use -f, -r, and/or -g to specify recipients.")
  371.             usage()
  372.  
  373.         allowable_mime_types = cups.getAllowableMIMETypes()
  374.         allowable_mime_types.append("application/hplip-fax")
  375.         allowable_mime_types.append("application/x-python")
  376.  
  377.         for f in args:
  378.             path = os.path.realpath(f)
  379.             log.debug(path)
  380.  
  381.             if os.path.exists(path):
  382.                 mime_type = magic.mime_type(path)
  383.                 log.debug(mime_type)
  384.             else:
  385.                 log.error("File '%s' does not exist." % path)
  386.                 sys.exit(1)
  387.  
  388.             if mime_type not in allowable_mime_types:
  389.                 log.error("File '%s' has a non-allowed mime-type of '%s'" % (path, mime_type))
  390.                 sys.exit(1)
  391.  
  392.         if printer_name:
  393.             printer_list = cups.getPrinters()
  394.             found = False
  395.             for p in printer_list:
  396.                 if p.name == printer_name:
  397.                     device_uri = p.device_uri
  398.                     found = True
  399.                     break
  400.  
  401.             if not found:
  402.                 log.error("Unknown printer name: %s" % printer_name)
  403.                 sys.exit(1)
  404.  
  405.             if not p.device_uri.startswith('hpfax:/'):
  406.                 log.error("You must specify a printer that has a device URI in the form 'hpfax:/'")
  407.                 sys.exit(1)
  408.  
  409.         if device_uri and not printer_name:
  410.             cups_printers = cups.getPrinters()
  411.  
  412.             max_printer_size = 20
  413.             printers = []
  414.             for p in cups_printers:
  415.                 try:
  416.                     back_end, is_hp, bus, model, serial, dev_file, host, port = \
  417.                         device.parseDeviceURI(p.device_uri)
  418.                 except Error:
  419.                     continue
  420.  
  421.                 if back_end == 'hpfax' and p.device_uri == device_uri:
  422.                     printers.append((p.name, p.device_uri))
  423.                     max_printer_size = max(len(p.name), max_printer_size)
  424.  
  425.             if not printers:
  426.                 log.error("No CUPS queue found for device %s" % device_uri)
  427.                 sys.exit(1)
  428.  
  429.             elif len(printers) == 1:
  430.                 printer_name = printers[0][0]
  431.  
  432.             else:
  433.                 log.info(log.bold("\nChoose printer (fax queue) from installed printers in CUPS:\n"))
  434.  
  435.                 formatter = utils.TextFormatter(
  436.                         (
  437.                             {'width': 4},
  438.                             {'width': max_printer_size, 'margin': 2},
  439.                         )
  440.                     )
  441.  
  442.                 log.info(formatter.compose(("Num.", "CUPS Printer (queue)")))
  443.                 log.info(formatter.compose(('-'*4, '-'*(max_printer_size), )))
  444.  
  445.                 i = 0
  446.                 for p in printers:
  447.                     log.info(formatter.compose((str(i), p[0])))
  448.                     i += 1
  449.  
  450.                 ok, x = tui.enter_range("\nEnter number 0...%d for printer (q=quit) ?" % (i-1), 0, (i-1))
  451.  
  452.                 if not ok: 
  453.                     sys.exit(0)
  454.  
  455.                 printer_name = printers[x][0]
  456.  
  457.         if not device_uri and not printer_name:
  458.             cups_printers = cups.getPrinters()
  459.             log.debug(cups_printers)
  460.  
  461.             printers = []
  462.             max_deviceid_size, max_printer_size = 0, 0
  463.  
  464.             for p in cups_printers:
  465.                 try:
  466.                     back_end, is_hp, bus, model, serial, dev_file, host, port = \
  467.                         device.parseDeviceURI(p.device_uri)
  468.                 except Error:
  469.                     continue
  470.  
  471.                 if back_end == 'hpfax':
  472.                     printers.append((p.name, p.device_uri))
  473.                     max_deviceid_size = max(len(p.device_uri), max_deviceid_size)
  474.                     max_printer_size = max(len(p.name), max_printer_size)
  475.  
  476.             if not printers:
  477.                 log.error("No devices found.")
  478.                 sys.exit(1)
  479.  
  480.             if len(printers) == 1:
  481.                 printer_name, device_uri = printers[0]
  482.  
  483.             else:
  484.                 log.info(log.bold("\nChoose printer (fax queue) from installed printers in CUPS:\n"))
  485.  
  486.                 formatter = utils.TextFormatter(
  487.                         (
  488.                             {'width': 4},
  489.                             {'width': max_printer_size, 'margin': 2},
  490.                             {'width': max_deviceid_size, 'margin': 2},
  491.                         )
  492.                     )
  493.  
  494.                 log.info(formatter.compose(("Num.", "CUPS Printer", "Device URI")))
  495.                 log.info(formatter.compose(('-'*4, '-'*(max_printer_size), '-'*(max_deviceid_size))))
  496.  
  497.                 i = 0
  498.                 for p in printers:
  499.                     log.info(formatter.compose((str(i), p[0], p[1])))
  500.                     i += 1
  501.  
  502.                 ok, x = tui.enter_range("\nEnter number 0...%d for printer (q=quit) ?" % (i-1), 0, (i-1))
  503.  
  504.                 if not ok: 
  505.                     sys.exit(0)
  506.  
  507.                 printer_name, device_uri = printers[x]
  508.  
  509.  
  510.         log.info(log.bold("Using printer %s (%s)" % (printer_name, device_uri)))
  511.  
  512.         ok, lock_file = utils.lock_app('hp-sendfax-%s' % printer_name, True)
  513.         try:            
  514.             ppd_file = cups.getPPD(printer_name)
  515.  
  516.             if ppd_file is not None and os.path.exists(ppd_file):
  517.                 if file(ppd_file, 'r').read(8192).find('HP Fax') == -1:
  518.                     log.error("Fax configuration error. The CUPS fax queue for '%s' is incorrectly configured. Please make sure that the CUPS fax queue is configured with the 'HP Fax' Model/Driver." % printer_name)
  519.                     sys.exit(1)
  520.  
  521.             if not args:
  522.                 log.error("No files specfied to send. Please specify the file(s) to send on the command line.")
  523.                 usage()
  524.  
  525.             file_list = []
  526.  
  527.             for f in args:
  528.  
  529.                 #
  530.                 # Submit each file to CUPS for rendering by hpijsfax
  531.                 #
  532.                 path = os.path.realpath(f)
  533.                 log.debug(path)
  534.                 mime_type = magic.mime_type(path)
  535.  
  536.                 if mime_type == 'application/hplip-fax': # .g3
  537.                     log.info("\nPreparing fax file %s..." % f)
  538.                     fax_file_fd = file(f, 'r')
  539.                     header = fax_file_fd.read(fax.FILE_HEADER_SIZE)
  540.                     fax_file_fd.close()
  541.  
  542.                     mg, version, pages, hort_dpi, vert_dpi, page_size, \
  543.                         resolution, encoding, reserved1, reserved2 = struct.unpack(">8sBIHHBBBII", header)
  544.  
  545.                     if mg != 'hplip_g3':
  546.                         log.error("%s: Invalid file header. Bad magic." % f)
  547.                         sys.exit(1)
  548.  
  549.                     file_list.append((f, mime_type, "", "", pages))
  550.  
  551.                 else:
  552.                     all_pages = True 
  553.                     page_range = ''
  554.                     page_set = 0
  555.                     nup = 1
  556.  
  557.                     cups.resetOptions()
  558.  
  559.                     if mime_type in ["application/x-cshell",
  560.                                      "application/x-perl",
  561.                                      "application/x-python",
  562.                                      "application/x-shell",
  563.                                      "text/plain",] and prettyprint:
  564.  
  565.                         cups.addOption('prettyprint')
  566.  
  567.                     if nup > 1:
  568.                         cups.addOption('number-up=%d' % nup)
  569.  
  570.                     cups_printers = cups.getPrinters()
  571.                     printer_state = cups.IPP_PRINTER_STATE_STOPPED
  572.                     for p in cups_printers:
  573.                         if p.name == printer_name:
  574.                             printer_state = p.state
  575.  
  576.                     log.debug("Printer state = %d" % printer_state)
  577.  
  578.                     if printer_state == cups.IPP_PRINTER_STATE_IDLE:
  579.                         log.debug("Printer name = %s file = %s" % (printer_name, path))
  580.                         sent_job_id = cups.printFile(printer_name, path, os.path.basename(path))
  581.                         log.info("\nRendering file '%s' (job %d)..." % (path, sent_job_id))
  582.                         log.debug("Job ID=%d" % sent_job_id)
  583.                     else:
  584.                         log.error("The CUPS queue for '%s' is in a stopped or busy state. Please check the queue and try again." % printer_name)
  585.                         sys.exit(1)
  586.  
  587.                     cups.resetOptions()
  588.  
  589.                     #
  590.                     # Wait for fax to finish rendering
  591.                     #
  592.  
  593.                     end_time = time.time() + 120.0 
  594.                     while time.time() < end_time:
  595.                         log.debug("Waiting for fax...")
  596.                         try:
  597.                             result = list(service.CheckForWaitingFax(device_uri, prop.username, sent_job_id))
  598.                             log.debug(repr(result))
  599.                             
  600.                         except dbus.exceptions.DBusException:
  601.                             log.error("Cannot communicate with hp-systray. Canceling...")
  602.                             cups.cancelJob(sent_job_id)
  603.                             sys.exit(1)
  604.  
  605.                         fax_file = str(result[7])
  606.                         log.info(fax_file)
  607.  
  608.                         if fax_file:
  609.                             log.debug("Fax file=%s" % fax_file)
  610.                             title = str(result[5])
  611.                             break
  612.  
  613.                         time.sleep(1)
  614.  
  615.                     else:
  616.                         log.error("Timeout waiting for rendering. Canceling job #%d..." % sent_job_id)
  617.                         cups.cancelJob(sent_job_id)
  618.                         sys.exit(1)
  619.  
  620.                     # open the rendered file to read the file header
  621.                     f = file(fax_file, 'r')
  622.                     header = f.read(fax.FILE_HEADER_SIZE)
  623.  
  624.                     if len(header) != fax.FILE_HEADER_SIZE:
  625.                         log.error("Invalid fax file! (truncated header or no data)")
  626.                         sys.exit(1)
  627.  
  628.                     mg, version, total_pages, hort_dpi, vert_dpi, page_size, \
  629.                         resolution, encoding, reserved1, reserved2 = \
  630.                         struct.unpack(">8sBIHHBBBII", header[:fax.FILE_HEADER_SIZE])
  631.  
  632.                     log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" %
  633.                               (mg, version, total_pages, hort_dpi, vert_dpi, page_size, resolution, encoding))
  634.  
  635.                     file_list.append((fax_file, mime_type, "", title, total_pages))
  636.                     f.close()
  637.  
  638.             #
  639.             # Insure that the device is in an OK state
  640.             #
  641.  
  642.             dev = None
  643.  
  644.             log.debug("\nChecking device state...")
  645.             try:
  646.                 dev = fax.getFaxDevice(device_uri, printer_name)
  647.  
  648.                 try:
  649.                     dev.open()
  650.                 except Error, e:
  651.                     log.warn(e.msg)
  652.  
  653.                 try:
  654.                     dev.queryDevice(quick=True)
  655.                 except Error, e:
  656.                     log.error("Query device error (%s)." % e.msg)
  657.                     dev.error_state = ERROR_STATE_ERROR
  658.  
  659.                 if dev.error_state > ERROR_STATE_MAX_OK and \
  660.                     dev.error_state not in (ERROR_STATE_LOW_SUPPLIES, ERROR_STATE_LOW_PAPER):
  661.  
  662.                     log.error("Device is busy or in an error state (code=%d). Please wait for the device to become idle or clear the error and try again." % dev.error_state)
  663.                     sys.exit(1)
  664.  
  665.                 user_cfg.last_used.device_uri = dev.device_uri
  666.  
  667.                 log.debug("File list:")
  668.  
  669.                 for f in file_list:
  670.                     log.debug(str(f))
  671.  
  672.                 service.SendEvent(device_uri, printer_name, EVENT_START_FAX_JOB, prop.username, 0, '')
  673.  
  674.                 update_queue = Queue.Queue()
  675.                 event_queue = Queue.Queue()
  676.  
  677.                 log.info("\nSending fax...")
  678.  
  679.                 if not dev.sendFaxes(phone_num_list, file_list, "", 
  680.                                      "", None, False, printer_name,
  681.                                      update_queue, event_queue):
  682.  
  683.                     log.error("Send fax is active. Please wait for operation to complete.")
  684.                     service.SendEvent(device_uri, printer_name, EVENT_FAX_JOB_FAIL, prop.username, 0, '')
  685.                     sys.exit(1)
  686.  
  687.                 try:
  688.                     cont = True
  689.                     while cont:
  690.                         while update_queue.qsize():
  691.                             try:
  692.                                 status, page_num, phone_num = update_queue.get(0)
  693.                             except Queue.Empty:
  694.                                 break
  695.  
  696.                             if status == fax.STATUS_IDLE:
  697.                                 log.debug("Idle")
  698.  
  699.                             elif status == fax.STATUS_PROCESSING_FILES:
  700.                                 log.info("\nProcessing page %d" % page_num)
  701.  
  702.                             elif status == fax.STATUS_DIALING:
  703.                                 log.info("\nDialing %s..." % phone_num)
  704.  
  705.                             elif status == fax.STATUS_CONNECTING:
  706.                                 log.info("\nConnecting to %s..." % phone_num)
  707.  
  708.                             elif status == fax.STATUS_SENDING:
  709.                                 log.info("\nSending page %d to %s..." % (page_num, phone_num))
  710.  
  711.                             elif status == fax.STATUS_CLEANUP:
  712.                                 log.info("\nCleaning up...")
  713.  
  714.                             elif status in (fax.STATUS_ERROR, fax.STATUS_BUSY, fax.STATUS_COMPLETED):
  715.                                 cont = False
  716.  
  717.                                 if status  == fax.STATUS_ERROR:
  718.                                     log.error("Fax send error.")
  719.                                     service.SendEvent(device_uri, printer_name, EVENT_FAX_JOB_FAIL, prop.username, 0, '')
  720.  
  721.                                 elif status == fax.STATUS_BUSY:
  722.                                     log.error("Fax device is busy. Please try again later.")
  723.                                     service.SendEvent(device_uri, printer_name, EVENT_FAX_JOB_FAIL, prop.username, 0, '')
  724.  
  725.                                 elif status == fax.STATUS_COMPLETED:
  726.                                     log.info("\nCompleted successfully.")
  727.                                     service.SendEvent(device_uri, printer_name, EVENT_END_FAX_JOB, prop.username, 0, '')
  728.  
  729.                         update_spinner()
  730.                         time.sleep(2)
  731.  
  732.                     cleanup_spinner()
  733.  
  734.                 except KeyboardInterrupt:
  735.                     event_queue.put((fax.EVENT_FAX_SEND_CANCELED, '', '', ''))
  736.                     service.SendEvent(device_uri, printer_name, EVENT_FAX_JOB_CANCELED, prop.username, 0, '')
  737.                     log.error("Cancelling...")
  738.  
  739.             finally:
  740.                 log.debug("Waiting for send fax thread to exit...")
  741.                 if dev is not None:
  742.                     dev.waitForSendFaxThread()
  743.                     log.debug("Closing device...")
  744.                     dev.close()
  745.  
  746.         finally:
  747.             utils.unlock(lock_file)
  748.         
  749.     except KeyboardInterrupt:
  750.         log.error("User exit")    
  751.  
  752.     
  753.         
  754. log.info("")
  755. log.info("Done.")
  756.  
  757.  
  758.  
  759.  
  760.